package cc.rengu.igas.opms.core.service.trans.apppay;

import cc.rengu.chargecalc.mchntfee.CalcMchntFee;
import cc.rengu.chargecalc.mchntfee.enums.CalcFlagEnum;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeBean;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeResultBean;
import cc.rengu.igas.acct.facade.bean.MchtAdjustDetail;
import cc.rengu.igas.acct.facade.request.VirtAcctMultiMchntAdjustRequest;
import cc.rengu.igas.momp.facade.base.Header;
import cc.rengu.igas.momp.facade.bean.ClaimCouponMcInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderCouponInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.request.ClaimCouponRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentResponse;
import cc.rengu.igas.momp.facade.result.Result;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.constant.OpmsServiceConstant;
import cc.rengu.igas.opms.common.constant.OpmsTreeNodeConstant;
import cc.rengu.igas.opms.common.entity.QuickPayTxnNumInfo;
import cc.rengu.igas.opms.common.entity.TransLimitBean;
import cc.rengu.igas.opms.common.enums.CardTypeEnum;
import cc.rengu.igas.opms.common.enums.FeeTypeEnum;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.PayService;
import cc.rengu.igas.opms.facade.request.MobileBankScanPayRequest;
import cc.rengu.igas.opms.facade.response.MobileBankScanPayResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.enums.SettleAcctTypeEnum;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntAcctInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.CsmcService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.CsmcServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderDetailMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderDetailMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.*;
import cc.rengu.oltp.service.realize.impl.BinInfoServiceImpl;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 手机银行扫码快捷支付
 * Created by fyp on 2020/3/30.
 * modify by wangcheng 2021-09-13
 */
public class MobileBankScanPayService extends PayService implements TransCustomImpl {
    private boolean isCouponTrans = false;

    @Override
    protected Object bizBeforeCust() throws Exception {
        MobileBankScanPayRequest mobileBankScanPayRequest = new MobileBankScanPayRequest();
        ConvertUtil.convertOutput(mobileBankScanPayRequest);
        return mobileBankScanPayRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        MobileBankScanPayRequest mobileBankScanPayRequest = (MobileBankScanPayRequest) request;
        String instId = mobileBankScanPayRequest.getHeader().getInstId();
        String acctType = null;

        //处理订单金额格式
        mobileBankScanPayRequest.setOrderAmt(AmountUtil.checkAmt(mobileBankScanPayRequest.getOrderAmt(), 2));

        // 商户号
        String transMchntNo = mobileBankScanPayRequest.getMchntNo();
        /* 获取卡bin信息 */
        BinInfoService binInfoService = new BinInfoServiceImpl();
        BinInfo binInfo = binInfoService.getCardBinInfo(mobileBankScanPayRequest.getAcctNo());
        if (binInfo == null) {
            rglog.error("根据卡号<{}>查询卡bin信息失败", mobileBankScanPayRequest.getAcctNo());
            throw new BizException(RespCodeEnum.GET_CARD_BIN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_CARD_BIN_INFO_ERROR.getRespDesc());
        }

        // 校验支付密码---主扫都要调用
//        UserService userService = new UserServiceImpl();
//        boolean checkResult = userService.checkUserPayPassword(instId,mobileBankScanPayRequest.getUserId(),mobileBankScanPayRequest.getOrderAmt(),mobileBankScanPayRequest.getPassword());
//        if (!checkResult){
//            rglog.error("用户支付密码错误!");
//            throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(),RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
//        }
        // 生成订单
        UserOrderInfo userOrderInfo = createUserOrder(mobileBankScanPayRequest);
        /*获取商户订单*/
        List<MchntOrderInfo> mchntOrderInfoList = makeMchntOrderInfo(mobileBankScanPayRequest);

        /*遍历商户订单，检查商户状态 、商户权限*/
        if (CardTypeEnum.DEBIT.getAcctType().equals(binInfo.getCardType())) {
            acctType = AcctTypeEnum.BANK_DEBIT.getAcctType();
        } else if (CardTypeEnum.CREDIT.getAcctType().equals(binInfo.getCardType()) ||
                CardTypeEnum.QCREDIT.getAcctType().equals(binInfo.getCardType())) {
            acctType = AcctTypeEnum.BANK_CREDIT.getAcctType();
        } else {
            rglog.error("不支持的卡类型<{}>", binInfo.getCardType());
            throw new BizException(RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespDesc());
        }
        // 817行扫码使用信用卡支付时必分期（后台修改）
        if ("817".equals(instId)
                && AcctTypeEnum.BANK_CREDIT.getAcctType().equals(acctType)) {
            rglog.error("威海银行使用信用卡，必须分期<{}>", acctType);
            throw new BizException(RespCodeEnum.WEIHAI_QCREDIT_STAGE.getRespCode(), RespCodeEnum.WEIHAI_QCREDIT_STAGE.getRespDesc());
        }

        /*转换商户订单信息，权限检查校验*/
        List<TransLimitBean> transLimitBeanList = convMchntOrderInfo(mobileBankScanPayRequest, transMchntNo, acctType, userOrderInfo, mchntOrderInfoList);
        //交易限额信息存入缓存
        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.TRANS_LIMIT_INFO_LIST, transLimitBeanList);
        /*初始化订单服务*/
        OrderService orderService = new OrderServiceImpl();
        /*更新订单明细表*/
        List<MchntOrderDetail> mchntOrderDetailList = new ArrayList<>();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            MchntOrderDetailMapper mchntOrderDetailMapper = new MchntOrderDetailMapperImpl();
            List<MchntOrderDetail> oneMchntOrderDetailList = mchntOrderDetailMapper.selectMchntOrderDetailByMchntOrderId(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo(), mchntOrderInfo.getMchntOrderId());
            if (!CollectionUtils.isEmpty(oneMchntOrderDetailList)) {
                for (MchntOrderDetail mchntOrderDetail : oneMchntOrderDetailList) {
                    mchntOrderDetail.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
                }
                mchntOrderDetailList.addAll(oneMchntOrderDetailList);
            }
        }
        if (!CollectionUtils.isEmpty(mchntOrderDetailList)) {
            orderService.updateOrderInfo(null, null, mchntOrderDetailList, null);
        }
        /*新建用户订单表*/
        if (!orderService.registerOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
            rglog.error("更新订单信息失败");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(),
                    RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
        }

        //查询交易配置
        Predicate<ChannelCallCfg> bizType = p -> mobileBankScanPayRequest.getHeader().getBizType().equals(p.getBizType());
        Predicate<ChannelCallCfg> esbId = p -> ChannelEnum.ESB.getChannelType().equals(p.getCallChannelId());
        //借记卡和贷记卡交易配置
        List<ChannelCallCfg> esbChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(bizType.and(esbId)).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        //营销交易配置
        List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        //虚拟账户配置
        List<ChannelCallCfg> acctChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ACCT.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());

        QuickPayTxnNumInfo txnNumInfo = new QuickPayTxnNumInfo();
        //借记卡记账交易配置
        txnNumInfo.setDebitChannelCallCfg(esbChannelCallCfgList.get(0));
        //贷记卡记账交易配置
        if (esbChannelCallCfgList.size() > 1) {
            txnNumInfo.setPredictChannelCallCfg(esbChannelCallCfgList.get(1));
        }
        //营销合并支付交易配置
        txnNumInfo.setMompChannelCallCfg(mompChannelCallCfgList.get(0));
        //营销合并支付冲正交易配置
        if (mompChannelCallCfgList.size() > 1) {
            txnNumInfo.setMompRevsalChannelCallCfg(mompChannelCallCfgList.get(1));
        }
        //虚拟账户记账交易配置
        txnNumInfo.setAcctChannelCallCfg(acctChannelCallCfgList.get(0));

        //准备参数
//        QuickPayRequest quickPayRequest = new QuickPayRequest();
//        BeanUtil.beanCopy(mobileBankScanPayRequest, quickPayRequest);
//        quickPayRequest.setHeader(mobileBankScanPayRequest.getHeader());
//        quickPayRequest.setOrderChanlId(" ");
//        quickPayRequest.setQuickPayTxnNumInfo(txnNumInfo);
//        quickPayRequest.setSignType(SignTokenTypeEnum.BANK_QUICK_PAY.getSignTypeCode());
//        quickPayRequest.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
//        //调用快捷支付公共方法
//        PublicDealService publicDealService = new PublicDealServiceImpl();
//        QuickPayResponse quickPayResponse = publicDealService.quickPay(quickPayRequest);
        //处理返回结果
        MobileBankScanPayResponse response = new MobileBankScanPayResponse();
//        response.setOrderAmt(quickPayResponse.getOrderAmt());
//        response.setActualAmt(quickPayResponse.getActualAmt());
//        response.setDiscountAmt(quickPayResponse.getDiscountAmt());

        //返回结果
        BizResponse<MobileBankScanPayResponse> bizResponse = new BizResponse();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setResult(response);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;

        /*

         *//*判断借贷记调用不同接口处理*//*
        if (CardTypeEnum.DEBIT.getAcctType().equals(binInfo.getCardType())) {
            return debitCardPay(mobileBankScanPayRequest, userOrderInfo, mchntOrderInfoList);
        } else if (CardTypeEnum.CREDIT.getAcctType().equals(binInfo.getCardType()) ||
                CardTypeEnum.QCREDIT.getAcctType().equals(binInfo.getCardType())) {
            return creditCardPay(mobileBankScanPayRequest, userOrderInfo, mchntOrderInfoList);
        } else {
            rglog.error("不支持的卡类型<{}>", binInfo.getCardType());
            throw new BizException(RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespDesc());
        }*/
    }

    /**
     * 创建商户订单
     *
     * @return 商户订单
     * @throws Exception 异常
     */
    private List<MchntOrderInfo> makeMchntOrderInfo(MobileBankScanPayRequest mobileBankScanPayRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<MchntOrderInfo> mchntOrderList = new ArrayList<>();
        MchntOrderInfo mchntOrderInfo = new MchntOrderInfo();
        mchntOrderInfo.setInstId(mobileBankScanPayRequest.getHeader().getInstId());
        mchntOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        mchntOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        mchntOrderInfo.setTxnNum(mobileBankScanPayRequest.getHeader().getTxnNum());
        mchntOrderInfo.setBizType(mobileBankScanPayRequest.getHeader().getBizType());
        mchntOrderInfo.setBizProdCode(BaseProdEnum.SCAN_CODE.getProdCode());
        mchntOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        mchntOrderInfo.setMchntOrderId(mobileBankScanPayRequest.getUserOrderId());
        mchntOrderInfo.setAcqInstCode(mchntInfo.getSignInstId());
        mchntOrderInfo.setIndustryType(mchntInfo.getIndustryType());
        mchntOrderInfo.setMchntNo(mobileBankScanPayRequest.getMchntNo());
        mchntOrderInfo.setMchntName(mchntInfo.getMchntName());
        //mchntOrderInfo.setUserId(mobileBankScanPayRequest.getUserId());
        mchntOrderInfo.setOrderCcy("156");
        mchntOrderInfo.setOrderAmt(mobileBankScanPayRequest.getOrderAmt());
        mchntOrderInfo.setRealSettleAmt(mobileBankScanPayRequest.getOrderAmt());
        mchntOrderInfo.setRealSettleFlag(mchntInfo.getRealSettleFlag());
        mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        //判断商户是否是独立清算的门店商户
        if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
            rglog.debug("非独立维护资料的门店商户商户订单表记录其连锁商户号");
            mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
        }
        mchntOrderList.add(mchntOrderInfo);

        return mchntOrderList;
    }

    /**
     * 用户订单生成
     *
     * @param mobileBankScanPayRequest
     * @return
     * @throws Exception
     */
    private UserOrderInfo createUserOrder(MobileBankScanPayRequest mobileBankScanPayRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        UserOrderInfo userOrderInfo = new UserOrderInfo();
        userOrderInfo.setInstId(mobileBankScanPayRequest.getHeader().getInstId());// 机构标识
        userOrderInfo.setTxnDate(DateUtil.getCurrentDate());// 交易日期
        userOrderInfo.setTxnTime(DateUtil.getCurrentTime());// 交易时间
        userOrderInfo.setTxnNum(mobileBankScanPayRequest.getHeader().getTxnNum());// 内部交易码
        userOrderInfo.setBizType(mobileBankScanPayRequest.getHeader().getBizType());// 业务细分
        userOrderInfo.setMsgSrcId(mobileBankScanPayRequest.getHeader().getSrcSysId());// 源系统标识
        // 交易渠道--行级别的--使用行号
        //userOrderInfo.setTransChannelId(mobileBankScanPayRequest.getHeader().getChanlId());// 交易渠道标识
        userOrderInfo.setTransChannelId(OpmsParamConstant.MOBILE_BANK_CHANNEL_ID);//默认手机银行

        userOrderInfo.setMchntOrderId(mobileBankScanPayRequest.getUserOrderId()); // 商户订单号不存子啊，使用系统流水号
        userOrderInfo.setUserId(mobileBankScanPayRequest.getUserId());//核心客戶號
        userOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));// 系统流水号
        userOrderInfo.setOrderCreateTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"));// 订单创建时间
        userOrderInfo.setOrderAmt(mobileBankScanPayRequest.getOrderAmt());
        userOrderInfo.setRealPayAmt(mobileBankScanPayRequest.getOrderAmt());
        userOrderInfo.setOrderCcy("156");

        // 默认是30分钟
        // 订单有效时间
        userOrderInfo.setOrderExpiryTime(DateUtil.getDateByTimeStamp(System.currentTimeMillis() + 1800 * 1000, "yyyyMMddHHmmss"));
        userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        // 01-业务处理中 40-授权未完成【待密码认证】
        userOrderInfo.setBizStatus(BizStatusEnum.INIT.getStatus());
        userOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return userOrderInfo;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        MobileBankScanPayResponse mobileBankScanPayResponse = (MobileBankScanPayResponse) bizResponse.getResult();
        ConvertUtil.convertInput(mobileBankScanPayResponse);
    }

    /**
     * 信用卡快捷支付
     *
     * @param mobileBankScanPayRequest
     * @return
     * @throws Exception
     */
    private BizResponse creditCardPay(MobileBankScanPayRequest mobileBankScanPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        DubboService dubboService = new DubboServiceImpl();
        Predicate<ChannelCallCfg> bizType = p -> "00".equals(p.getBizType());
        Predicate<ChannelCallCfg> esbId = p -> ChannelEnum.ESB.getChannelType().equals(p.getCallChannelId());
        List<ChannelCallCfg> esbChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(bizType.and(esbId)).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());

        String discountFlag = "N";
        int iReturnCode = 0;
        BizResponse<MobileBankScanPayResponse> bizResponse = new BizResponse();
        MobileBankScanPayResponse mobileBankScanPayResponse = new MobileBankScanPayResponse();
        mobileBankScanPayResponse.setHeader(mobileBankScanPayRequest.getHeader());
        OrderService orderService = new OrderServiceImpl();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String realPayAmt = mobileBankScanPayRequest.getOrderAmt();
        /*调用银数密码校验接口*/

        /*调用营销接口进行优惠试算*/
        /*登记支付订单表*/
        PayOrderInfo payOrderInfo = registerPayOrderInfo(userOrderInfo, mobileBankScanPayRequest, AcctTypeEnum.BANK_CREDIT.getAcctType(), mompChannelCallCfgList.get(0));
        if (payOrderInfo == null) {
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }
        ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
        ConvertUtil.convertOutput(comboPaymentRequest);
        Header header = new Header();
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setBizType("00");
        header.setTxnNum(payOrderInfo.getDstTxnNum());
        header.setVersion("1.0.0");
        header.setTraceNo(sysSeqNum + payOrderInfo.getDstCallIndex());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTransDate(DateUtil.getCurrentDate());
        comboPaymentRequest.setHeader(header);
        comboPaymentRequest.setUserId(userOrderInfo.getUserId());

        /*获取营销产品编码*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(userOrderInfo.getInstId(), OpmsParamConstant.MOMP_PROD_CODE,
                mobileBankScanPayRequest.getHeader().getTxnNum() + mobileBankScanPayRequest.getHeader().getBizType());
        if (sysParam != null) {
            comboPaymentRequest.setBizProdCode(sysParam.getParamValue());
        }
        comboPaymentRequest.setMchntOrderId(userOrderInfo.getMchntOrderId());
        comboPaymentRequest.setTransAmt(userOrderInfo.getNeedPayAmt());
        List<PaymentOrderDetailBean> orderDetailList = new ArrayList<>();
        convertOrderDetail(orderDetailList, mchntOrderInfoList);
        comboPaymentRequest.setOrderDetailList(orderDetailList);
        if (mobileBankScanPayRequest.getCouponInfo() != null && mobileBankScanPayRequest.getCouponInfo().getDiscountId() != null) {
            discountFlag = "Y";
            List<PaymentOrderCouponInfoBean> couponInfoList = new ArrayList<>();
            PaymentOrderCouponInfoBean paymentOrderCouponInfoBean = new PaymentOrderCouponInfoBean();
            paymentOrderCouponInfoBean.setCouponNo(mobileBankScanPayRequest.getCouponInfo().getDiscountId());
            comboPaymentRequest.setCouponInfoList(couponInfoList);
        }
        Result<ComboPaymentResponse> responseResult = (Result<ComboPaymentResponse>) dubboService.callDubboService("paymentService", "comboPayment", comboPaymentRequest);
        if (null == responseResult || !responseResult.isSuccess()) {
            rglog.error("调用dubbo服务comboPayment失败");
            /*更新订单表状态*/
            userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            }

            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }
            mobileBankScanPayResponse.setRespCode(RespCodeEnum.SYSTEM_ERROR.getRespCode());
            mobileBankScanPayResponse.setRespDesc(RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            bizResponse.setResult(mobileBankScanPayResponse);
            return bizResponse;
        } else {
            ComboPaymentResponse comboPaymentResponse = responseResult.getResult();
            if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.YES.equals(discountFlag)) {
                /*业务响应失败*/
                rglog.error("调用服务失败，返回码respCode=[]，respDesc=[{}]", comboPaymentResponse.getRespCode(), comboPaymentResponse.getRespDesc());
                /*更新订单表状态*/
                userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                    mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                }

                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                }

                mobileBankScanPayResponse.setRespCode(comboPaymentResponse.getRespCode());
                mobileBankScanPayResponse.setRespDesc(comboPaymentResponse.getRespDesc());
                bizResponse.setResult(mobileBankScanPayResponse);
                return bizResponse;
            } else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.NO.equals(discountFlag)) {
                /*更新支付订单表状态失败，由于未使用优惠券，可继续往下支付*/
                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                payOrderInfo.setRealPayAmt("0.00");
                if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
                }
            } else {
                /*营销系统返回成功，更新订单支付订单状态为成功*/
                payOrderInfo.setRealPayAmt(comboPaymentResponse.getTxnAmt());
                payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                /*更新商户订单表*/
                if (AmountUtil.compare(comboPaymentResponse.getTransAmt(), comboPaymentResponse.getTxnAmt()) != 0) {
                    /*参与营销，不实时入账*/
                    discountFlag = "N";
                    realPayAmt = comboPaymentResponse.getTxnAmt();
                    List<PaymentOrderDetailBean> orderDetailBeanList = comboPaymentResponse.getOrderDetailList();
                    if (orderDetailBeanList == null || orderDetailBeanList.isEmpty()) {
                        rglog.error("营销返回数据有误");
                        throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                    }
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        List<PaymentOrderDetailBean> paymentOrderDetailBeanList = orderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfo.getMchntNo())).collect(Collectors.toList());
                        if (paymentOrderDetailBeanList == null || paymentOrderDetailBeanList.isEmpty()) {
                            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                        }

                        mchntOrderInfo.setMchntDiscountFee(paymentOrderDetailBeanList.get(0).getMchntFeeDiscount());
                        /*商户结算金额*/
                        String mchntTotalSettleAmt = AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getMchntFee());
                        mchntTotalSettleAmt = AmountUtil.addition(mchntTotalSettleAmt, mchntOrderInfo.getMchntDiscountFee());
                        if ("0".equals(paymentOrderDetailBeanList.get(0).getMoneyOffSettlementMethod())) {
                            mchntTotalSettleAmt = AmountUtil.subtraction(mchntTotalSettleAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal());
                        }
                        if ("0".equals(paymentOrderDetailBeanList.get(0).getCouponMchntSettleMethod())) {
                            mchntTotalSettleAmt = AmountUtil.subtraction(mchntTotalSettleAmt, paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy());
                        }
                        /*用户优惠金额*/
                        String moneyOffSubsidyTotal = "0.00";
                        String couponTotalSubsidy = "0.00";
                        if (paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal() != null) {
                            moneyOffSubsidyTotal = paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal();
                        }
                        if (paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy() != null) {
                            couponTotalSubsidy = paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy();
                        }
                        mchntOrderInfo.setCustomerMarketAmt(AmountUtil.addition(moneyOffSubsidyTotal, couponTotalSubsidy));
                        mchntOrderInfo.setRealSettleFlag(discountFlag);
                        mchntOrderInfo.setMchntSettleAmt(mchntTotalSettleAmt);
                        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    }
                }
                if (!orderService.updateOrderInfo(null, mchntOrderInfoList, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
                }
            }
        }

        /*登记支付订单表*/
        PayOrderInfo esbPayOrderInfo = registerPayOrderInfo(userOrderInfo, mobileBankScanPayRequest, AcctTypeEnum.BANK_CREDIT.getAcctType(), esbChannelCallCfgList.get(1));
        if (payOrderInfo == null) {
            if (AppParamConstant.YES.equals(discountFlag)) {
                /*参与营销，异步调用营销冲正接口*/
                ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
                header.setTxnNum("P02MO001");
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                comboPaymentRevsalRequest.setOrigTraceNo(userOrderInfo.getMchntOrderId());
                header.setTraceNo(sysSeqNum + String.valueOf(Integer.parseInt(payOrderInfo.getDstCallIndex()) + 1));
                comboPaymentRevsalRequest.setHeader(header);
                iReturnCode = dubboService.asynCallDubboService("paymentService", OpmsParamConstant.DUBBO_METHOD_MOMP_REVERSAL, comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
                if (iReturnCode != 0) {
                    rglog.error("异步营销冲正服务注册失败！");
                }
            }
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        /* 调用esb银数消费接口 */
        //TODO step1.调用本行快捷支付  -贷记卡  分析调用结果，由项目组实现该部分交易
        // （1）通讯级失败或业务失败，调用营销冲正 mompRevsal，更新订单为失败，updateOrderFail，抛出调用业务异常
        // （2）业务超时，更新支付订单为处理中，抛出调用异常为处理中
        // （3）业务成功，更新订单状态，程序继续执行


        /*更新商户累计限额*/
        MchntService mchntService = new MchntServiceImpl();
        mchntService.updateMchntTransLimit(mchntOrderInfoList);

        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);
        claimCoupon(mchntOrderInfoList);
        /*筛选d0入账商户订单列表*/
        List<MchntOrderInfo> d0MchntOrderInfoList = mchntOrderInfoList.stream().filter(item -> item.getRealSettleFlag().equals(AppParamConstant.YES)).collect(Collectors.toList());
        /*非d0*/
        List<MchntOrderInfo> d1MchntOrderInfoList = mchntOrderInfoList.stream().filter(item -> item.getRealSettleFlag().equals(AppParamConstant.NO)).collect(Collectors.toList());
        /*判断是否实时入账*/
        if (d0MchntOrderInfoList != null && !d0MchntOrderInfoList.isEmpty()) {
            /*调用esb记账*/
            mchntRealTimeAccouting(d0MchntOrderInfoList, esbChannelCallCfgList.get(2));
        }
        if (d1MchntOrderInfoList != null || !d1MchntOrderInfoList.isEmpty()) {
            /*非d0支付后异步调用虚拟记账接口*/
            virtAcctMultiMchntAdjust(mobileBankScanPayRequest, userOrderInfo, d1MchntOrderInfoList);
        }

        if (userOrderInfo.getNotifyBackUrl() != null && !userOrderInfo.getNotifyBackUrl().isEmpty()) {
            /*异步通知给商户后台系统*/

        }

        mobileBankScanPayResponse.setDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), realPayAmt));
        mobileBankScanPayResponse.setActualAmt(realPayAmt);
        bizResponse.setResult(mobileBankScanPayResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    /**
     * 借记卡快捷支付
     *
     * @param mobileBankScanPayRequest
     * @return
     * @throws Exception
     */
    private BizResponse debitCardPay(MobileBankScanPayRequest mobileBankScanPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        DubboService dubboService = new DubboServiceImpl();
        Predicate<ChannelCallCfg> bizType = p -> mobileBankScanPayRequest.getHeader().getBizType().equals(p.getBizType());
        Predicate<ChannelCallCfg> esbId = p -> ChannelEnum.ESB.getChannelType().equals(p.getCallChannelId());
        List<ChannelCallCfg> esbChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(bizType.and(esbId)).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());

        String discountFlag = "N";
        String feeDiscountFlag = "N";

        int iReturnCode = 0;
        BizResponse<MobileBankScanPayResponse> bizResponse = new BizResponse();
        MobileBankScanPayResponse mobileBankScanPayResponse = new MobileBankScanPayResponse();
        mobileBankScanPayResponse.setHeader(mobileBankScanPayRequest.getHeader());
        OrderService orderService = new OrderServiceImpl();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String realPayAmt = mobileBankScanPayRequest.getOrderAmt();
        /*调用核心密码校验接口*/

        /*调用营销接口进行优惠试算 TODO */
        /*登记支付订单表*/
        PayOrderInfo payOrderInfo = registerPayOrderInfo(userOrderInfo, mobileBankScanPayRequest, AcctTypeEnum.BANK_CREDIT.getAcctType(), mompChannelCallCfgList.get(0));
        if (payOrderInfo == null) {
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }
        ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
        ConvertUtil.convertOutput(comboPaymentRequest);
        Header header = new Header();
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setBizType("00");
        header.setTxnNum(payOrderInfo.getDstTxnNum());
        header.setVersion("1.0.0");
        header.setTraceNo(sysSeqNum + payOrderInfo.getDstCallIndex());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTransDate(DateUtil.getCurrentDate());
        comboPaymentRequest.setHeader(header);
        comboPaymentRequest.setUserId(userOrderInfo.getUserId());

        /*获取营销产品编码*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(userOrderInfo.getInstId(), OpmsParamConstant.MOMP_PROD_CODE,
                mobileBankScanPayRequest.getHeader().getTxnNum() + mobileBankScanPayRequest.getHeader().getBizType());
        if (sysParam != null) {
            comboPaymentRequest.setBizProdCode(sysParam.getParamValue());
        }
        comboPaymentRequest.setMchntOrderId(userOrderInfo.getMchntOrderId());
        comboPaymentRequest.setTransAmt(userOrderInfo.getOrderAmt());
        List<PaymentOrderDetailBean> orderDetailList = new ArrayList<>();
        convertOrderDetail(orderDetailList, mchntOrderInfoList);
        comboPaymentRequest.setOrderDetailList(orderDetailList);
        if (mobileBankScanPayRequest.getCouponInfo() != null && mobileBankScanPayRequest.getCouponInfo().getDiscountId() != null) {
            discountFlag = "Y";
            List<PaymentOrderCouponInfoBean> couponInfoList = new ArrayList<>();
            PaymentOrderCouponInfoBean paymentOrderCouponInfoBean = new PaymentOrderCouponInfoBean();
            paymentOrderCouponInfoBean.setCouponNo(mobileBankScanPayRequest.getCouponInfo().getDiscountId());
            comboPaymentRequest.setCouponInfoList(couponInfoList);
        }
        Result<ComboPaymentResponse> responseResult = (Result<ComboPaymentResponse>) dubboService.callDubboService("paymentService", "comboPayment", comboPaymentRequest);
        if (null == responseResult || !responseResult.isSuccess()) {
            rglog.error("调用dubbo服务comboPayment失败");
            if (AppParamConstant.YES.equals(discountFlag)) {
                /*更新订单表状态*/
                userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                    mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                }

                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

                if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                }
                mobileBankScanPayResponse.setRespCode(RespCodeEnum.SYSTEM_ERROR.getRespCode());
                mobileBankScanPayResponse.setRespDesc(RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                bizResponse.setResult(mobileBankScanPayResponse);
                return bizResponse;
            }
            payOrderInfo.setRealPayAmt("0.00");
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }

        } else {
            ComboPaymentResponse comboPaymentResponse = responseResult.getResult();
            if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.YES.equals(discountFlag)) {
                /*业务响应失败*/
                rglog.error("调用服务失败，返回码respCode=[]，respDesc=[{}]", comboPaymentResponse.getRespCode(), comboPaymentResponse.getRespDesc());
                /*更新订单表状态*/
                userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                    mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                }

                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                }

                mobileBankScanPayResponse.setRespCode(comboPaymentResponse.getRespCode());
                mobileBankScanPayResponse.setRespDesc(comboPaymentResponse.getRespDesc());
                bizResponse.setResult(mobileBankScanPayResponse);
                return bizResponse;
            } else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.NO.equals(discountFlag)) {
                /*更新支付订单表状态失败，由于未使用优惠券，可继续往下支付*/
                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                payOrderInfo.setRealPayAmt("0.00");
                if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
                }
            } else {

                //调用营销超时
                if (OpmsParamConstant.DUBBO_OVERTIME.equals(comboPaymentResponse.getRespCode())) {
                    rglog.warn("营销调用超时，发起营销合并支付冲正，交易终止");
                    updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                    xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                    mompRevsal();
                }
                //调用营销系统失败，但用户使用优惠劵进行支付。交易终止
                else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && isCouponTrans) {
                    /*业务响应失败*/
                    rglog.warn("调用服务失败，返回码respCode=[]，respDesc=[{}]", comboPaymentResponse.getRespCode(), comboPaymentResponse.getRespDesc());
                    updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                    throw new BizException(comboPaymentResponse.getRespCode(), comboPaymentResponse.getRespDesc());
                }
                //调用营销系统失败，用户未使用优惠劵。交易继续进行
                else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.NO.equals(discountFlag)) {

                    payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    payOrderInfo.setRealPayAmt("0.00");
                    if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                        rglog.warn("更新订单表状态失败");
                        throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
                    }
                } else {

                    //判断是否使用营销 参与营销，不实时入账
                    if (AmountUtil.compare(comboPaymentResponse.getTransAmt(), comboPaymentResponse.getTxnAmt()) != 0) {
                        discountFlag = AppParamConstant.YES;
                    }

                    realPayAmt = comboPaymentResponse.getTxnAmt();
                    //用户订单表数据更新
                    if (mobileBankScanPayRequest.getCouponInfo() != null && mobileBankScanPayRequest.getCouponInfo().getDiscountId() != null) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put(mobileBankScanPayRequest.getCouponInfo().getDiscountId(), mobileBankScanPayRequest.getCouponInfo().getDiscountAmt());
                        userOrderInfo.setDiscountInfo(jsonObject.toJSONString());
                    }
                    userOrderInfo.setRealDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), realPayAmt));

                    List<PaymentOrderDetailBean> orderDetailBeanList = comboPaymentResponse.getOrderDetailList();
                    if (orderDetailBeanList == null || orderDetailBeanList.isEmpty()) {
                        rglog.warn("营销返回数据有误，订单明细列表未返回。orderDetailBeanListSize:<{}>", orderDetailBeanList.size());
                        updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                        xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                        mompRevsal();
                        throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                    }

                    //计算商户的优惠信息
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {

                        List<PaymentOrderDetailBean> paymentOrderDetailBeanList = orderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfo.getMchntNo())).collect(Collectors.toList());
                        if (paymentOrderDetailBeanList.isEmpty()) {
                            rglog.warn("当前商户无营销优惠信息，在订单明细列表中无当前商户数据。mchntNo:<{}>", mchntOrderInfo.getMchntNo());
                            updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                            xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                            mompRevsal();
                            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                        }

                        /*用户优惠金额*/
                        String moneyOffSubsidyTotal = "0.00";
                        String couponTotalSubsidy = "0.00";
                        if (paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal() != null) {
                            moneyOffSubsidyTotal = paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal();
                        }
                        if (paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy() != null) {
                            couponTotalSubsidy = paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy();
                        }
                        mchntOrderInfo.setCustomerMarketAmt(AmountUtil.addition(moneyOffSubsidyTotal, couponTotalSubsidy));

                        /*商户手续费优惠金额*/
                        String mchntFeeDiscount = mchntOrderInfo.getMchntDiscountFee();
                        String mchntFeeActual = mchntOrderInfo.getRealMchntFee();
                        if (paymentOrderDetailBeanList.get(0).getMchntFeeDiscount() != null && AmountUtil.compare(paymentOrderDetailBeanList.get(0).getMchntFeeDiscount(), "0") == 1) {
                            mchntFeeDiscount = paymentOrderDetailBeanList.get(0).getMchntFeeDiscount();
                            feeDiscountFlag = AppParamConstant.YES;
                        }
                        if (paymentOrderDetailBeanList.get(0).getMchntFeeActual() != null) {
                            mchntFeeActual = paymentOrderDetailBeanList.get(0).getMchntFeeActual();
                        }
                        mchntOrderInfo.setMchntDiscountFee(mchntFeeDiscount);
                        mchntOrderInfo.setRealMchntFee(mchntFeeActual);

                        /*商户结算金额*/
                        String channelDiscountAmt = "0.00";
                        String mchntTotalSettleAmt = AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntFeeActual);
                        if ("0".equals(paymentOrderDetailBeanList.get(0).getMoneyOffSettlementMethod())) {
                            /*免充值需要减去商户满减补贴金额*/
                            mchntTotalSettleAmt = AmountUtil.subtraction(mchntTotalSettleAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyMchnt());
                        } else {
                            /*通道优惠金额累加*/
                            channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal());
                        }
                        if ("0".equals(paymentOrderDetailBeanList.get(0).getCouponMchntSettleMethod())) {
                            /*免充值需要减去商户卡券补贴金额*/
                            mchntTotalSettleAmt = AmountUtil.subtraction(mchntTotalSettleAmt, paymentOrderDetailBeanList.get(0).getCouponMchntSubsidy());
                        } else {
                            /*通道优惠金额累加*/
                            channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy());
                        }
                        mchntOrderInfo.setMchntSettleAmt(mchntTotalSettleAmt);
                        payOrderInfo.setChannelDiscountAmt(channelDiscountAmt);
                        if (paymentOrderDetailBeanList.get(0).getCouponNo() != null) {
                            mchntOrderInfo.setRedeemCouponIds(paymentOrderDetailBeanList.get(0).getCouponNo());
                        }
                        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        mchntOrderInfo.setRealSettleFlag(OpmsParamConstant.OPMS_PARAM_NO);
                    }

                    /*营销系统返回成功，更新订单支付订单状态为成功*/
                    payOrderInfo.setRealPayAmt(AmountUtil.subtraction(comboPaymentResponse.getTransAmt(), comboPaymentResponse.getTxnAmt()));
                    payOrderInfo.setChannelDiscountAmt(comboPaymentResponse.getTotalSubsidy());
                    payOrderInfo.setSettleDate(DateUtil.getCurrentDate());
                    payOrderInfo.setRespCode(responseResult.getResult().getRespCode());
                    payOrderInfo.setRespDesc(responseResult.getResult().getRespDesc());
                    payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                    payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                        rglog.warn("更新营销支付订单表失败");
                    }
                }

                //是否使用优惠标识存入节点内
                if (AppParamConstant.NO.equals(discountFlag) && AppParamConstant.NO.equals(feeDiscountFlag)) {
                    xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);
                } else {
                    xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                }
            }
        }

        /*登记支付订单表*/
        PayOrderInfo esbPayOrderInfo = registerPayOrderInfo(userOrderInfo, mobileBankScanPayRequest, AcctTypeEnum.BANK_DEBIT.getAcctType(), esbChannelCallCfgList.get(0));
        if (payOrderInfo == null) {
            if (AppParamConstant.YES.equals(discountFlag)) {
                /*参与营销，异步调用营销冲正接口*/
                ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
                header.setTxnNum("P02MO001");
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                header.setTraceNo(sysSeqNum + String.valueOf(Integer.parseInt(payOrderInfo.getDstCallIndex()) + 1));
                comboPaymentRevsalRequest.setHeader(header);
                iReturnCode = dubboService.asynCallDubboService("paymentService", "comboPaymentRevsal", comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
                if (iReturnCode != 0) {
                    rglog.error("异步营销冲正服务注册失败！");
                }
            }
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        /* 调用esb核心消费接口 */
        //TODO step2.调用核心借记卡快捷支付  分析调用结果，由项目组实现该部分交易
        // （1）通讯级失败或业务失败（非超时/成功），调用营销冲正 mompRevsal，更新订单为失败，updateOrderFail，抛出调用业务异常
        // （2）业务超时，更新支付订单为处理中，抛出调用异常为处理中
        // （3）业务成功，更新订单状态，程序继续执行


        /*更新商户累计限额*/
        MchntService mchntService = new MchntServiceImpl();
        mchntService.updateMchntTransLimit(mchntOrderInfoList);

        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);
        claimCoupon(mchntOrderInfoList);
        /*筛选d0入账商户订单列表*/
        List<MchntOrderInfo> d0MchntOrderInfoList = mchntOrderInfoList.stream().filter(item -> item.getRealSettleFlag().equals(AppParamConstant.YES)).collect(Collectors.toList());
        /*非d0*/
        List<MchntOrderInfo> d1MchntOrderInfoList = mchntOrderInfoList.stream().filter(item -> item.getRealSettleFlag().equals(AppParamConstant.NO)).collect(Collectors.toList());
        /*判断是否实时入账*/
        if (d0MchntOrderInfoList != null && !d0MchntOrderInfoList.isEmpty()) {
            /*调用esb记账*/
            mchntRealTimeAccouting(d0MchntOrderInfoList, esbChannelCallCfgList.get(2));
        }
        if (d1MchntOrderInfoList != null || !d1MchntOrderInfoList.isEmpty()) {
            /*非d0支付后异步调用虚拟记账接口*/
            virtAcctMultiMchntAdjust(mobileBankScanPayRequest, userOrderInfo, d1MchntOrderInfoList);
        }

        if (userOrderInfo.getNotifyBackUrl() != null && !userOrderInfo.getNotifyBackUrl().isEmpty()) {
            /*异步通知给商户后台系统*/

        }

        mobileBankScanPayResponse.setDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), realPayAmt));
        mobileBankScanPayResponse.setActualAmt(realPayAmt);
        mobileBankScanPayResponse.setOrderAmt(esbPayOrderInfo.getOrderAmt());
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setResult(mobileBankScanPayResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    private PayOrderInfo registerPayOrderInfo(UserOrderInfo userOrderInfo, MobileBankScanPayRequest request, String acctType, ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /*获取渠道户*/
        rglog.debug("获取渠道户");
        CsmcService csmcService = new CsmcServiceImpl();
        String roleActualAcctNo = csmcService.getRoleActualAcctNo(xmlTreeUtil.getXmlTreeStringValue(OpmsTreeNodeConstant.INST_ID), SettleAcctTypeEnum.BANK_PAYCHNL_SUBJECT.getSettleAcct(), null);
        if (StringUtil.isEmptyOrNull(roleActualAcctNo)) {
            rglog.error("获取内部账户信息不存在，异常异常");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        String seqeuenceNumber = GlobalEsbUtil.generateEsbSeqeuenceNumber(userOrderInfo.getInstId());
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setOrderCcy(request.getOrderCcy());
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(seqeuenceNumber);
        payOrderInfo.setChannelReconKey(seqeuenceNumber);
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
        payOrderInfo.setPayerAcctType(acctType);
        payOrderInfo.setPayerAcctInfo(request.getAcctNo());//付款人
        payOrderInfo.setRealPayAmt(userOrderInfo.getRealPayAmt());
        payOrderInfo.setSettleDate(DateUtil.getCurrentDate());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        payOrderInfo.setPayeeAcctInfo(roleActualAcctNo);

        OrderService orderService = new OrderServiceImpl();
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }
        return payOrderInfo;
    }

    int updatePayOrderInfo(PayOrderInfo payOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppParamConstant.DATABASE_CONF_NODE, AppParamConstant.OLTP_POOL_NAME);
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);

        dbsUtil.dbsBeginTransaction();
        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        int recode = payOrderInfoMapper.updatePayOrderInfoByPrimaryKey(payOrderInfo);
        if (recode != 0) {
            dbsUtil.dbsEndTransaction(false);
            return recode;
        }
        dbsUtil.dbsEndTransaction(true);
        return recode;
    }

    void convertOrderDetail(List<PaymentOrderDetailBean> orderDetailList, List<MchntOrderInfo> mchntOrderInfoList) {
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            PaymentOrderDetailBean paymentOrderDetailBean = new PaymentOrderDetailBean();
            paymentOrderDetailBean.setMchntNo(mchntOrderInfo.getMchntNo());
            if (mchntOrderInfo.getOrderDiscountAmt() != null && !mchntOrderInfo.getOrderDiscountAmt().isEmpty()) {
                paymentOrderDetailBean.setOrderAmt(AmountUtil.subtraction(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getOrderDiscountAmt()));
            } else {
                paymentOrderDetailBean.setOrderAmt(mchntOrderInfo.getOrderAmt());
            }
            paymentOrderDetailBean.setMchntSettleAmt(mchntOrderInfo.getRealSettleAmt());
            paymentOrderDetailBean.setMchntFeeReceivable(mchntOrderInfo.getMchntFee());
            paymentOrderDetailBean.setMchntFeeReceivableRate(mchntOrderInfo.getFeeRate());
            orderDetailList.add(paymentOrderDetailBean);
        }
    }

    /*商户虚拟账户记账*/
    void virtAcctMultiMchntAdjust(MobileBankScanPayRequest mobileBankScanPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        //虚拟账户记账或预授权完成，购买卡券交易和担保支付交易不记虚拟账户
        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "01".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            rglog.info("购买卡券交易或担保支付的交易,bizSceneType:<{}>，不记商户虚拟账,但推送消息", mchntOrderInfoList.get(0).getBizSceneType());
            if (0 != asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0)) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
            return;
        }

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = null;
        DubboService dubboService = new DubboServiceImpl();
        List<ChannelCallCfg> ChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ACCT.getChannelType())).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = ChannelCallCfgList.get(0);
        String realPayAmt = "0.00";
        //商户收支两线的标识
        char incomeFlag = '1';

        /*记账前登记支付订单表*/
        try {
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
            VirtAcctMultiMchntAdjustRequest request = new VirtAcctMultiMchntAdjustRequest();
            cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
            BeanUtil.beanCopy(mobileBankScanPayRequest.getHeader(), header);
            header.setTxnNum(channelCallCfg.getCallChannelTxn());
            header.setTraceNo(sysSeqNum + channelCallCfg.getCallIndex());
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
            request.setHeader(header);
            request.setAcctType("00");
            request.setDebitCreditFlag("C");
            List<MchtAdjustDetail> mchtAdjustDetailList = new ArrayList<>();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                if ("00".equals(mchntOrderInfo.getFeeInputMode())) {
                    continue;
                }
                MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
                mchtAdjustDetail.setUserType("01");//01-商户
                mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                    mchtAdjustDetail.setUserId(mchntInfo.getChainMchntNo());
                } else {
                    mchtAdjustDetail.setUserId(mchntInfo.getMchntNo());
                }
                /*收支两线的商户使用商户清算本金金额到虚拟账户记账，合并轧差的商户使用商户结算净额到虚拟账户记账*/
                rglog.info("当前商户:<{}>的结算模式:<{}>", mchntInfo.getMchntNo(), mchntInfo.getMchntSettleMode());
                if (incomeFlag == mchntInfo.getMchntSettleMode().charAt(1)) {
                    realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getRealSettleAmt());
                    mchtAdjustDetail.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                } else {
                    realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getMchntSettleAmt());
                    mchtAdjustDetail.setTransAmt(mchntOrderInfo.getMchntSettleAmt());
                }
                //如果商户记虚拟账户的金额等于0则不记该商户的虚拟账户
                if (AmountUtil.compare("0", mchtAdjustDetail.getTransAmt()) == 0) {
                    continue;
                }
                mchtAdjustDetailList.add(mchtAdjustDetail);
            }

            if (mchtAdjustDetailList.isEmpty()) {
                /*特殊计费订单不记虚拟账，调用微信消息推送*/
                rglog.error("订单全为特殊计费，不记商户虚拟账，直接推送通知");
                int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
                if (0 != iReturnCode) {
                    rglog.error("提交交易结果异步通知给商户失败!");
                }
                return;
            }
            List<MchtAdjustDetail> mchtAdjustDetailListFinal = new ArrayList<>();
            /*按商户分组去重，累计求和*/
            Map<String, List<MchtAdjustDetail>> groupByUserId = mchtAdjustDetailList.stream().collect(Collectors.groupingBy(MchtAdjustDetail::getUserId));
            for (Map.Entry<String, List<MchtAdjustDetail>> entryUserId : groupByUserId.entrySet()) {
                String totalTransAmt = "0";
                String userId = entryUserId.getKey();
                List<MchtAdjustDetail> entryMchtAdjustDetailList = entryUserId.getValue();
                for (MchtAdjustDetail mchtAdjustDetail : entryMchtAdjustDetailList) {
                    totalTransAmt = AmountUtil.addition(totalTransAmt, mchtAdjustDetail.getTransAmt());
                }
                MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
                mchtAdjustDetail.setUserType("00");//01-商户
                mchtAdjustDetail.setUserId(userId);
                mchtAdjustDetail.setTransAmt(totalTransAmt);
                mchtAdjustDetailListFinal.add(mchtAdjustDetail);
            }
            request.setMchtAdjustDetailList(mchtAdjustDetailListFinal);

            //登记虚拟账户支付订单表
            PayOrderInfo acctPayOrderInfo = registerPayOrderInfo(userOrderInfo, mobileBankScanPayRequest, AcctTypeEnum.BANK_ACCT.getAcctType(), channelCallCfg);
            if (acctPayOrderInfo == null) {
                rglog.error("登记虚拟账户记账支付订单失败");
                return;
            }

            //异步调起虚拟账户记账服务
            int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_ACCT_VIRTACCT_SERVICE,
                    OpmsParamConstant.DUBBO_ACCT_VIRTACCTMULTIMCHNTADJUST, request, OpmsServiceConstant.ASYN_VIRTACCT_MULTIMCHNT_ADJUST_SERVICE);
            if (iReturnCode != 0) {
                rglog.error("异步虚拟账户记账服务注册失败！");
            } else {
                rglog.error("异步虚拟账户记账服务注册成功！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("登记虚拟账户记账支付订单失败");
        }

    }

    /*商户实时入账*/
    void mchntRealTimeAccouting(List<MchntOrderInfo> mchntOrderInfoList, ChannelCallCfg channelCallCfg) throws Exception {
        DubboService dubboService = new DubboServiceImpl();
        int callIndex = Integer.parseInt(channelCallCfg.getCallIndex());

        /*获取渠道户,默认为渠道户*/
        CsmcService csmcService = new CsmcServiceImpl();
        String roleActualAcctNo = csmcService.getRoleActualAcctNo(mchntOrderInfoList.get(0).getInstId(), SettleAcctTypeEnum.BANK_PAYCHNL_SUBJECT.getSettleAcct(), null);
        MchntService mchntService = new MchntServiceImpl();
        int iReturnCode = 0;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            /*查询商户结算账户信息表，判断结算周期及结算账户类型*/
            try {
                //获取商户结算账户
                List<MchntAcctInfo> mchntAcctInfoList;
                mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getBaseProdCode().equals(mchntOrderInfo.getBizProdCode()) && item.getFundType().equals("00")).findFirst();
                if (!mchntAcctInfoOpt.isPresent()) {
                    rglog.error("获取商户结算账户信息失败，商户实时入账失败，转t1");
                }

                //登记实时入账支付订单表
                PayOrderInfo payOrderInfo = registerD0PayOrderInfo(mchntOrderInfo, roleActualAcctNo, AcctTypeEnum.BANK_ACCT.getAcctType(),
                        mchntAcctInfoOpt.get().getSettleAcctNo(), mchntAcctInfoOpt.get().getSettleAcctType(), channelCallCfg, String.valueOf(callIndex));
                if (payOrderInfo == null) {
                    continue;
                }

                //调用入账
                //TODO 由项目组实现该部分 调用D0实时清算，后调用AsynMchntD0AccoutingService根据清算结果进行处理
                iReturnCode = dubboService.asynCallDubboService("dubboService", "method", "request", "AsynMchntD0AccoutingService");
                if (iReturnCode != 0) {
                    rglog.debug("商户<{}>异步d0入账服务注册失败！", mchntOrderInfo.getMchntNo());
                }
                callIndex++;
            } catch (Exception e) {
                rglog.error(e.getMessage());
            }
        }
    }

    /*登记D0记账支付订单流水*/
    private PayOrderInfo registerD0PayOrderInfo(MchntOrderInfo mchntOrderInfo, String payAcctNo, String payAcctType, String payeeAcctNo, String payeeAcctType, ChannelCallCfg channelCallCfg, String callIndex) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(mchntOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(OpmsParamConstant.D0_ACCOUTING_TXN_NUM);
        try {
            payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
            if (callIndex != null) {
                payOrderInfo.setDstCallIndex(callIndex);
                payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + callIndex);
                payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + callIndex);
            } else {
                payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
                payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
                payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
            }

            payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
            payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
            payOrderInfo.setPayerAcctType(payAcctType);
            payOrderInfo.setPayerAcctInfo(payAcctNo);
            payOrderInfo.setPayeeAcctType(payeeAcctType);
            payOrderInfo.setPayeeAcctInfo(payeeAcctNo);
            payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
                rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
                return null;
            }
            return payOrderInfo;
        } catch (Exception e) {
            rglog.error(e.getMessage());
            return null;
        }
    }

    List<TransLimitBean> convMchntOrderInfo(MobileBankScanPayRequest mobileBankScanPayRequest, String transMchntNo, String acctType, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = mobileBankScanPayRequest.getHeader().getInstId();
        String txnNum = mobileBankScanPayRequest.getHeader().getTxnNum();
        String bizType = mobileBankScanPayRequest.getHeader().getBizType();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        MchntService mchntService = new MchntServiceImpl();
        String feeType = null;
        if (AcctTypeEnum.BANK_DEBIT.getAcctType().equals(acctType)) {
            feeType = FeeTypeEnum.BANK_DR_CARD.getFeeType();
        } else {
            feeType = FeeTypeEnum.BANK_CR_CARD.getFeeType();
        }

        List<TransLimitBean> transLimitBeanList = new ArrayList<>();
        if (isCouponTrans) {
            /*卡券购买交易，不计算商户手续费，只需检查一次商户权限，商户号取自用户订单表*/
            MchntInfo mchntInfo = mchntService.getMchntInfo(instId, transMchntNo);
            if (null == mchntInfo) {
                rglog.error("查询商户基本信息失败<{}>", transMchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            /*交易权限检查*/
            boolean checkResult = mchntService.checkMchntAuth(instId, transMchntNo, null, txnNum, bizType, acctType);
            if (!checkResult) {
                rglog.error("商户<{}>无此交易权限!", transMchntNo);
                throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
            }
            /*限额检查*/
            int limitFlag = mchntService.checkMchntTransLimit(instId, userOrderInfo.getOrderAmt(), LimitAcctTypeEnum.ALL, transMchntNo, null, txnNum);
            if (limitFlag == 2 || limitFlag == 3) {
                rglog.error("商户金额超限");
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            } else if (limitFlag == 1) {
                /*不支持信用卡*/
                xmlTreeUtil.setXmlTreeStringValue("disablePayChannels", "pcredit");
            }

            if (mobileBankScanPayRequest.getCouponInfo() != null) {
                rglog.error("购买卡券不支持使用优惠券");
                throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
            }
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
                mchntOrderInfo.setTxnNum(txnNum);
                mchntOrderInfo.setSysSeqNum(sysSeqNum);
                mchntOrderInfo.setTxnDate(userOrderInfo.getTxnDate());
                mchntOrderInfo.setTxnTime(userOrderInfo.getTxnTime());
                mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
                mchntOrderInfo.setMchntDiscountFee("0.00");
                mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            }

        } else {
            /*非卡券购买遍历商户订单，检查商户状态 、商户权限*/
            CalcMchntFee clearMethod = new CalcMchntFee();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntOrderInfo.getMchntNo());
                if (null == mchntInfo) {
                    rglog.error("查询商户基本信息失败<{}>", mchntOrderInfo.getMchntNo());
                    throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
                }
                /*交易权限检查*/
                boolean checkResult = mchntService.checkMchntAuth(instId, mchntOrderInfo.getMchntNo(), null, txnNum, bizType, acctType);
                if (!checkResult) {
                    rglog.error("商户<{}>无此交易权限!", mchntOrderInfo.getMchntNo());
                    throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
                }
                /*限额检查*/
                int limitFlag = mchntService.checkMchntTransLimit(instId, mchntOrderInfo.getRealSettleAmt(), LimitAcctTypeEnum.ALL, mchntOrderInfo.getMchntNo(), null, txnNum);
                if (limitFlag == 2 || limitFlag == 3) {
                    rglog.error("商户金额超限");
                    throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
                } else if (limitFlag == 1) {
                    /*不支持信用卡*/
                    xmlTreeUtil.setXmlTreeStringValue("disablePayChannels", "pcredit");
                }

                /*计算商户手续费*/
                CalcMchntFeeBean clearSrcObj = new CalcMchntFeeBean();
                clearSrcObj.setMchntNo(mchntOrderInfo.getMchntNo());
                clearSrcObj.setTransAmt(mchntOrderInfo.getOrderAmt());
                clearSrcObj.setInstId(instId);
                clearSrcObj.setStageCode("");
                clearSrcObj.setStageNum("");
                clearSrcObj.setSubProdType(feeType);
                clearSrcObj.setIgasBizProdType(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
                CalcMchntFeeResultBean calcMchntFeeResultBean = clearMethod.calcPayFee(clearSrcObj);
                if (calcMchntFeeResultBean == null) {
                    rglog.error("计算商户手续费失败");
                    throw new BizException(RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespCode(), RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespDesc());
                }

                //特殊费率商户设置费率标示
                if (CalcFlagEnum.CALCFLAG_SPEFEENOTCALC.getCalcFlag().equals(calcMchntFeeResultBean.getCalcFlag())) {
                    mchntOrderInfo.setFeeInputMode("0");
                } else {
                    mchntOrderInfo.setFeeInputMode(calcMchntFeeResultBean.getFeeInputMode());
                }
                mchntOrderInfo.setFeeRate(calcMchntFeeResultBean.getFeeRate());
                mchntOrderInfo.setFeeCappingAmt(calcMchntFeeResultBean.getFeeCappingAmt());
                mchntOrderInfo.setFeeFixedAmt(calcMchntFeeResultBean.getFeeFixedAmt());
                mchntOrderInfo.setMchntFee(calcMchntFeeResultBean.getMchntFee());
                mchntOrderInfo.setTxnNum(txnNum);
                mchntOrderInfo.setSysSeqNum(sysSeqNum);
                mchntOrderInfo.setTxnDate(userOrderInfo.getTxnDate());
                mchntOrderInfo.setTxnTime(userOrderInfo.getTxnTime());
                mchntOrderInfo.setMchntDiscountFee("0.00");
                mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), calcMchntFeeResultBean.getMchntFee()));
                mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
                mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                    mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
                }

                //实时清算判断
                if (mobileBankScanPayRequest.getCouponInfo() != null && mobileBankScanPayRequest.getCouponInfo().getDiscountId() != null) {
                    mchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
                } else {
                    String realSettleFlag = mchntService.getRealSettleFlag(mchntInfo.getMchntNo(), txnInfo.getSrcTxnAuthCfg().getBizProdCode(), mchntOrderInfo.getBizSceneType(), mchntOrderInfo.getRealSettleAmt());
                    mchntOrderInfo.setRealSettleFlag(realSettleFlag);
                    if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                        mchntOrderInfo.setRealSettleType("99");
                    }
                }
            }
        }

        return transLimitBeanList;
    }

    /*领取卡券*/
    void claimCoupon(List<MchntOrderInfo> mchntOrderInfoList) {
        if (!"00".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            return;
        }
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        DubboService dubboService = new DubboServiceImpl();
        String reserve = null;
        try {
            Header header = new Header();
            header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setBizType("00");
            header.setTxnNum("P01MO001");
            header.setVersion("1.0.0");
            header.setTraceNo(mchntOrderInfoList.get(0).getSysSeqNum() + "0");
            header.setTransTime(DateUtil.getCurrentTime());
            header.setTransDate(DateUtil.getCurrentDate());
            ClaimCouponRequest claimCouponRequest = new ClaimCouponRequest();
            claimCouponRequest.setHeader(header);
            List<ClaimCouponMcInfoBean> mcInfoList = new ArrayList<>();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                ClaimCouponMcInfoBean claimCouponMcInfoBean = new ClaimCouponMcInfoBean();
                claimCouponMcInfoBean.setPurchaseAmt(mchntOrderInfo.getOrderAmt());
                claimCouponMcInfoBean.setClaimQuantity("1");
                reserve = mchntOrderInfo.getTermNo();
                if (reserve != null) {
                    String[] mcInfo = reserve.split("|");
                    claimCouponMcInfoBean.setRuleIndex(mcInfo[1]);
                    claimCouponMcInfoBean.setMcNo(mcInfo[0]);
                }
                claimCouponMcInfoBean.setClaimUser(mchntOrderInfo.getUserId());
                claimCouponMcInfoBean.setClaimType("4");
                claimCouponMcInfoBean.setCouponLockFlag("1");
                mcInfoList.add(claimCouponMcInfoBean);
            }
            claimCouponRequest.setMcInfoList(mcInfoList);
            int iReturnCode = dubboService.asynCallDubboService("couponManagementService", "claimCoupon", claimCouponRequest, "AsynClaimCouponService");
            if (iReturnCode != 0) {
                rglog.error("异步卡券领取服务注册失败！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("异步卡券领取服务注册失败！");
        }
    }

    /**
     * 更新 订单为失败
     *
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @param orderService       订单组件
     * @throws Exception 异常
     */
    private void updateOrderFail(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo, OrderService orderService) throws Exception {
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        /*更新订单表状态*/
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        userOrderInfo.setUpdateTime(currentDateTime);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            mchntOrderInfo.setUpdateTime(currentDateTime);
        }

        if (null == payOrderInfo) {
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
                rglog.error("更新订单表状态失败");
            }
        } else {
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            payOrderInfo.setUpdateTime(currentDateTime);
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }
        }
    }

    /**
     * 营销合并支付冲正
     */
    void mompRevsal() {
        DubboService dubboService = new DubboServiceImpl();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            if (xmlTreeUtil.isExist("discountFlag") && AppParamConstant.YES.equals(xmlTreeUtil.getXmlTreeStringValue("discountFlag"))) {
                List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
                String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);

                /*参与营销，异步调用营销冲正接口*/
                ComboPaymentRequest comboPaymentRequest = (ComboPaymentRequest) xmlTreeUtil.getXmlTreeObjectValue("comboPaymentRequest", ComboPaymentRequest.class);
                Header header = comboPaymentRequest.getHeader();
                header.setTxnNum(mompChannelCallCfgList.get(1).getCallChannelTxn());
                header.setTraceNo(sysSeqNum + mompChannelCallCfgList.get(1).getCallIndex());
                ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                comboPaymentRevsalRequest.setHeader(header);
                int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, OpmsParamConstant.DUBBO_METHOD_MOMP_REVERSAL, comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
                if (iReturnCode != 0) {
                    rglog.error("异步营销冲正服务注册失败！");
                }
            } else {
                return;
            }
        } catch (Exception e) {
            rglog.error("营销异步冲正服务调用异常:<{}>", e);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item ->
                item.getBizScene().equals(ShareParamConstant.CALL_CFG_DEFAULT_BIZ_SCENE)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return transStatusEnum;
    }
}
